package main

import "fmt"

/*
go -- 函数式编程
func function_name([参数列表])([返回值列表]){
	函数体
}

支持：
可变长参数
函数也是一种类型，可以作为参数传递、赋值
支持匿名函数、闭包
支持多个返回值
支持命名参数返回
不支持：
一般情况下，不支持嵌套
不支持重载 （一个包中函数的名字不能重名）
不支持默认参数

程序运行必须要有一个main函数，main函数一般都是作为整个程序的入口
 */
type i int
//把接受两个int类型，返回一个int类型 定义成MyFunc
type MyFunc func(int,int) int

var a i
var b int

//不同类型之间，不能运算

//python --》解释性语言，动态类型语言，强类型语言
//go --》编译型语言，静态类型语言，强类型语言

//shell中默认的语言是字符串

func main(){
	//f :=func1  //函数本身也是一种结构体，可以赋值
	//f()

	//result :=func1()  //函数没有返回值，不能调用函数赋值
	//fmt.Println(result)
	//fmt.Println(add(9,10))
	//myargs()
	//myargs(1)
	//myargs(1,2)
	//myargs(1,2,3)
	//a = 10

	//把函数作为参数传入
	//result := test(getadd,3,4)
	//fmt.Println(result)

	//匿名函数 -- 没有名字的函数
	//把函数作为一种类型去使用，去赋值，去返回  通常使用匿名函数
	//a := func(){
	//	fmt.Println("匿名函数1......")
	//}
	//定义时直接调用
	//a := func(num1,num2 int) int {
	//	return num1+num2
	//}(3,5)
	//fmt.Println(a)
	//f := myfunc()()
	//fmt.Println(f)

	//调用闭包函数
	inner := closure(100)
	result := inner(200)
	fmt.Println(result)

}

//func func1(){
//	fmt.Println("i am func1")
//	func (){
//		fmt.Println("i am func2")
//	}()
//}

//func add(num1 int, num2 int) (int,int) {
//	result1 := num1 + num2
//	result2 := num1 - num2
//	return result1,result2
//}

//支持给返回值命名
//func add(num1 int, num2 int) (result int){
//	result = num1 + num2
//	return
//}

//可变长参数传递
//func myargs(nums... int){
//	fmt.Printf("%T --> %v \n", nums, nums )
//}

//go语言中可以支持自定义类型
//基本语法 type Myint int
//func getadd(a, b int) int {
//	return a + b
//}

//把函数作为参数传入
//func test(func1 MyFunc, num1, num2 int) int {
//	return func1(num1, num2)
//}

//func test(func2 func(int,int) int, num1, num2 int) int {
//	return func2(num1,num2)
//}

////把函数作为参数返回
//func myfunc() func() int {
//	return func() int {
//		fmt.Println("把函数作为参数返回")
//		return 10
//	}
//}

//闭包	概念
/*
1、有内外函数
2、外函数要返回内函数
3、内函数要引用外函数的变量


函数内的局部变量，一般情况下调用的时候生成，结束就释放
 */
// 在闭包的条件下，局部变量不会随着调用的结束而释放
func closure(x int) func(int) int{
	fmt.Println(x)
	return func(y int) int {
		fmt.Println("x is:", x)
		fmt.Println("y is:", y)
		return x+y
	}
}